import type { ConfigEnv, UserConfig } from 'vite';

import type { DefineLibraryOptions } from '../typing';

import { readPackageJSON } from '@croco/node-utils';

import { defineConfig, mergeConfig } from 'vite';

import { loadLibraryPlugins } from '../plugins';
import { getCommonConfig } from './common';

function defineLibraryConfig(userConfigPromise?: DefineLibraryOptions) {
    return defineConfig(async (config: ConfigEnv) => {
        const options = await userConfigPromise?.(config);
        const { command, mode } = config;
        const { library = {}, vite = {} } = options || {};
        const root = process.cwd();
        const isBuild = command === 'build';

        const plugins = await loadLibraryPlugins({
            dts: false,
            injectMetadata: true,
            isBuild,
            mode,
            ...library,
        });

        const { dependencies = {}, peerDependencies = {} } = await readPackageJSON(root);

        const externalPackages = [...Object.keys(dependencies), ...Object.keys(peerDependencies)];

        const packageConfig: UserConfig = {
            build: {
                lib: {
                    entry: 'src/index.ts',
                    fileName: () => 'index.mjs',
                    formats: ['es'],
                },
                rollupOptions: {
                    external: (id) => {
                        return externalPackages.some((pkg) => id === pkg || id.startsWith(`${pkg}/`));
                    },
                },
            },
            plugins,
        };
        const commonConfig = await getCommonConfig();
        const mergedConmonConfig = mergeConfig(commonConfig, packageConfig);
        return mergeConfig(mergedConmonConfig, vite);
    });
}

export { defineLibraryConfig };
